package com.mac.hosp_pre.order.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.service.WxPayService;
import com.mac.hosp_pre.except.ResultCodeEnum;
import com.mac.hosp_pre.except.ServiceException;
import com.mac.hosp_pre.order.config.WxPayProperties;
import com.mac.hosp_pre.order.entity.OrderInfo;
import com.mac.hosp_pre.order.enums.WxPayStateEnum;
import com.mac.hosp_pre.order.model.resp.PaymentRespDto;
import com.mac.hosp_pre.order.service.OrderService;
import com.mac.hosp_pre.order.service.PaymentService;
import com.mac.hosp_pre.order.service.RefundInfoService;
import com.mac.hosp_pre.order.service.WeixinService;
import com.mac.hosp_pre.order.util.RedisUtil;
import com.mac.hosp_pre.reply.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class WeixinServiceImpl implements WeixinService {

    static final String REDIS_GEN_CODE_PREFIX = "order_gen_code:";

    @Autowired
    private OrderService orderService;

    @Autowired
    private PaymentService paymentService;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private RefundInfoService refundInfoService;

    @Autowired
    private WxPayService wxPayService;

    @Autowired
    private WxPayProperties wxPayProperties;



    @Transactional(rollbackFor = Exception.class)
    @Override
    public R createNative(String outTradeNo) {
        OrderInfo one = orderService.getOne(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getOutTradeNo, outTradeNo));
        if (one == null){
            return R.error(ResultCodeEnum.NOT_EXISTS_ERROR.getCode(),"订单不存在");
        }
        Map<String,Object> payMap = (Map<String,Object>)redisUtil.getCacheObject(REDIS_GEN_CODE_PREFIX + outTradeNo);
        if (payMap != null){
            return R.success(payMap);
        }
        try {
            WxPayUnifiedOrderResult unifiedOrderResult = new WxPayUnifiedOrderResult();
            //6 封装返回结果集
            Map<String,Object> map = new HashMap<>();
            map.put("outTradeNo", outTradeNo);
            map.put("totalFee", one.getAmount());
            if (WxPayStateEnum.SUCCESS.name().equals(unifiedOrderResult.getResultCode())){
                map.put("codeUrl", unifiedOrderResult.getCodeURL()); //二维码地址
                redisUtil.setCacheObject(REDIS_GEN_CODE_PREFIX+outTradeNo,map,30, TimeUnit.MINUTES);
                return R.success(map);
            }else{
                return R.error(ResultCodeEnum.INTERNAL_SERVER_ERROR.getCode(),unifiedOrderResult.getReturnMsg());
            }
        } catch (Exception e) {
            log.error("微信支付异常：{}",e);
            throw new ServiceException(ResultCodeEnum.INTERNAL_SERVER_ERROR.getCode(),e.getMessage());
        }
    }

    @Override
    public R queryPayStatus(String outTradeNo) {
        OrderInfo one = orderService.getOne(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getOutTradeNo, outTradeNo));
        if (one == null){
            return R.error(ResultCodeEnum.NOT_EXISTS_ERROR.getCode(),"订单不存在");
        }
        try {
            WxPayOrderQueryResult orderQueryResult = new WxPayOrderQueryResult();
            if(WxPayStateEnum.SUCCESS.name().equals(orderQueryResult.getTradeState()) || WxPayStateEnum.getFailStates().contains(orderQueryResult.getTradeState())) { //支付成功
                R<Object> success = R.success();
                if (WxPayStateEnum.SUCCESS.name().equals(orderQueryResult.getTradeState())){
                    success.setMessage("支付成功");
                }else{
                    success.setMessage("支付失败");
                }
                return success;
            }
        } catch (Exception e) {
            log.error("微信支付查询异常：{}",e);
            throw new ServiceException(ResultCodeEnum.INTERNAL_SERVER_ERROR.getCode(),e.getMessage());
        }
        R<Object> success = R.success();
        success.setMessage("支付中");
        return success;
    }

    @Override
    public Boolean refund(Long orderId) {
        //获取支付记录信息
        PaymentRespDto paymentInfo = paymentService.getPaymentInfo(orderId);
        if(paymentInfo == null) {
            throw new ServiceException(ResultCodeEnum.INTERNAL_SERVER_ERROR.getCode(), "付款信息不存在");
        }
        try {
            WxPayRefundResult refunded = new WxPayRefundResult();
            log.info("订单编码:{},微信退款码：{}", paymentInfo.getOutTradeNo(),refunded.getResultCode());
            if (WxPayStateEnum.SUCCESS.name().equals(refunded.getResultCode())) {
                return true;
            }else {
                log.error("订单编码:{},微信退款失败报文:{}",paymentInfo.getOutTradeNo(),refunded);
                throw new ServiceException(ResultCodeEnum.INTERNAL_SERVER_ERROR.getCode(),refunded.getErrCodeDes());
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public String payNotify(HttpServletRequest request) {
        try {
            return WxPayNotifyResponse.success("处理成功!");
        }catch (Exception e){
            log.error("微信支付回调处理异常：{}",e);
        }
        return WxPayNotifyResponse.fail("处理失败!");
    }

    @Override
    public String refundNotify(HttpServletRequest request) {
        try {
            return WxPayNotifyResponse.success("处理成功!");
        } catch (Exception e){
            log.error("微信退款回调处理异常：{}",e);
        }
        return WxPayNotifyResponse.fail("处理失败!");
    }
}
